
/* Generated by Interface Builder */

#import "Pluck.h"
#import "Instrum.h"
#import <appkit/graphics.h>
#import "Statement.h"

@implementation Pluck

+ initialize
{
   	image = [NXImage findImageNamed:"Pluck"];
	dynamOffset.x = 3;
	dynamOffset.y = 30;
	ampOffset.x = 30;
	ampOffset.y = 52;
	freqOffset.x = 52;
	freqOffset.y = 30;
	outOffset.x = 30;
	outOffset.y = 8;
	
	return self;
}

- init
{
	written = NO;
	size.width = 80.;
	size.height = 80.;
	center.x = size.width/2.;
	center.y = size.height/2.;
	strcpy(type,"Pluck");
	strcpy(name,"hpluck");
	
	dynam = [[Param alloc] init:self :&dynamOffset];
	amp = [[Param alloc] init:self :&ampOffset];
	freq = [[Param alloc] init:self :&freqOffset];
	out = [[Param alloc] init:self :&outOffset];

	[freq setValue:"440"];	
	[dynam setTitle:"Dynam:"];
	[amp setTitle:"Amp:"];
	[freq setTitle:"Freq:"];
	[out setTitle:"Out:"];

	paramList = [[List alloc] initCount:4];
	[paramList addObject:dynam];
	[paramList addObject:amp];
	[paramList addObject:freq];
	[paramList addObject:out];
	
	[Inst putUgenInList:self];
	
	return self;
}

- remove
{
	id cp,param;
	int i;
							// make sure not connected first 
	for(i = 0; i < ([paramList count]); i++) {	
		param = [paramList objectAt:i];
		if(cp = [param getConnectedParam]) 
			return 0;
	}
							// remove ugen from list
	[Inst removeUgenFromList:self];
	return self;
}

- (NXImage *)getImage
{
	return image;
}

- move:(NXPoint *)newloc
{
	location = *newloc;
	[dynam move:&location];
	[amp move:&location];
	[freq move:&location];
	[out move:&location];
	return self;
}

- findParamAtPoint:(NXPoint *)point
{
	NXRect *rect;
	int i;
	id param;
	
	for(i = 0; i < [paramList count]; i++) {
		param = [paramList objectAt:i];
		rect = [param getRect];
		if(NXMouseInRect(point,rect,NO))
			return param;
	}
	return nil;
}

- writeUgen
{
	/* 	for amp param:
			see if there is input ugen - (not yet -- add pluckin stuff later)
				if so, grab the output (ug?) and multiply it by this
					param value
				if not just use the param value
	 	after all params done, write relevant code into lists
			(declarations, assignments and loop statements)
			i.e. ug? = oscil(,,,,);
		go to output param connected ugen and call its "writeUgen"
	*/
	BOOL rm;
	char ampVar[10];
	int i;
	int parent[3];
	id param;
	id ug;
	id nupar;
	char str[50];
	char par[20];
	
	//printf("writing ugen %d\n",index);
	sprintf(str,"\tfloat ug%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat dynam%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat amp%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat freq%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat out%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat loopt%d;\n",index);
	[Inst putVarInList:str];
	sprintf(str,"\tfloat  *q%d;\n",index);
	[Inst putVarInList:str];

	for(i = 0; i < ([paramList count]-1); i++) {	
		param = [paramList objectAt:i];
		if(nupar = [param getConnectedParam]) {
			ug = [nupar getUgen];
			if([ug getWritten] == NO) { 
				parent[i] = [[ug writeUgen] getIndex];
			}
			else  {
				parent[i] = 0;
			}
		}
		else 
			parent[i] = 0;
		
	}

/*	
	if(parent[0]) { 	// amplitude input ugen	
		rm = YES;
		sprintf(str,"\t\tamp%d = %.2f;\n",index, 
			atof([[paramList objectAt:0] getValue]));
		[Inst putLoopInList:str];
		sprintf(str,"\tfloat amprm%d;\n",index);
		[Inst putVarInList:str];
		sprintf(str,"\t\tamprm%d = amp%d * ug%d;\n",index,  
			index,parent[0]);
		[Inst putLoopInList:str];
	}
	else {				// amp preset or default
*/
		rm = NO;
		//printf("amp preset or default\n");
		sprintf(str,"\tamp%d = %.2f;\n",index,atof([[paramList objectAt:1] getValue]));
		[Inst putAssignInList:str];
//	}
	
//	if(rm)
//		sprintf(ampVar,"amprm%d",index);
//	else
		sprintf(ampVar,"amp%d",index);
		
					// dynam:
	strcpy(par,[[paramList objectAt:0] getValue]);
	if(par[0] == 'p' && par[1] == '[')
		sprintf(str,"\tdynam%d = %s;\n",index,par);
	else
		sprintf(str,"\tdynam%d = %.2f;\n", index, atof([[paramList objectAt:0] getValue]));
	[Inst putAssignInList:str];

								// pitch
	strcpy(par,[[paramList objectAt:2] getValue]);
	if(par[0] == 'p' && par[1] == '[')
		sprintf(str,"\tloopt%d = 1/%s;\n", index, par);
	else
		sprintf(str,"\tloopt%d = 1/%.2f;\n", index, atof(par));
	[Inst putAssignInList:str];

					// output amplitude multiplier:
	strcpy(par,[[paramList objectAt:3] getValue]);
	if(par[0] == 'p' && par[1] == '[')
		sprintf(str,"\tout%d = %s;\n",index,par);
	else
		sprintf(str,"\tout%d = %.2f;\n", index, atof([[paramList objectAt:3] getValue]));
	[Inst putAssignInList:str];

						// 	allocate memory for q array
	sprintf(str,"\tif((q%d = (float *)malloc((int)((loopt%d*SR+20) *  4))) == 0) {\n", index, index);
	[Inst putAssignInList:str];
	sprintf(str,"\t\tprintf(\"can't malloc memory for delayline\");\n\t\texit(-1);\n\t}\n");
	[Inst putAssignInList:str];
	
						// 	set up pluck
						//    	hplset(loopt,realpluckdur,dynam,pluckamp,seed,SR,1,q)
	sprintf(str, "\thplset(loopt%d,p[1],dynam%d,amp%d,0.414,SR,1,q%d);\n",index,index,index, index);
	[Inst putAssignInList:str];

	sprintf(str,"\t\tug%d = %s(0., q%d)*out%d;\n", index, name, index, index);
	[Inst putLoopInList:str];
	
	sprintf(str,"\tfree(q%d);\n", index);
	[Inst putEndInList:str];

	written = YES;
	return self;	
}

@end
